In [26]:
# Loading Required Modules and Setting Up the Plotting Environment
%matplotlib notebook
import usnc
import os
from sympy import symbols, exp, IndexedBase
import numpy as np
from sympy.utilities.codegen import codegen
from numpy import matrix, exp
from scipy.optimize import least_squares
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from sympy.printing import fcode
from sklearn.metrics.regression import r2_score, explained_variance_score, mean_absolute_error, median_absolute_error
from scipy.interpolate import interp1d
# Choice for units are Temperature (degC), Fluence (dpa) Force (N), Stress (Pa) and length (m)
# Adjust units accordingly and convert data to be consistent with a FEM package
NOTEBOOKPATH = r'/mnt/c/CalculiX/ingsm'
os.chdir(NOTEBOOKPATH)
# NAME OF THE DATASET
DATASET = 'HAAG.xls'
# PATH WHERE CALCULIX SOURCE CODE IS LOCATED
FORTRANPATH = r'/mnt/c/CalculiX/ccx_2.12/src/'
# NAME OF THE CALCULIX EXECUTABLE
CCXNAME = 'ccx_2.12'
# NAME OF THE FORTRAN MATERIAL FILE
FORTRANFILE = "umat.f"
# NAME WHERE ANSYS FILE SHOULD BE WRITTEN TO
ANSYSPATH = r'/mnt/c/CalculiX/ingsm/'
# NAME OF THE ANSYS MATERIAL FILE
ANSYSFILE = "usermat.F"
# PATH WHERE THE DATASET AND TESTS*.INP ARE LOCATED
DATAPATH = r'/mnt/c/CalculiX/ingsm'
# Define the properties for the three canonical directions
D1 = 'par';D2 = 'par';D3 = 'per'
# Define material properties (v = Poisson ratio, G1,G2,G3 Shear Modulus (Pa))
v = 0.15; G1 = 2E3; G2 = 2E3; G3 = 2E3;
# Define stress free temperature for computing thermal strains
Ti = 20.0
# Primary and Secondary Creep Fitting Data and Parameters
# Initial Guess for Primary and Secondary Creep Parameters
PCREEP = np.array([5.44550279 , 2.25226513 , 0.81541919])
NumPointsCreepIntegration = 101
# Stress state at which experimental data and tests were conducted
stress1 = np.array([5,0,0,0,0,0])
stress2 = np.array([5,0,0,0,0,0])
# Initial primary (Ecp1) and secondary creep (Ecs1)
Ecp1 = np.array([0,0,0,0,0,0])
Ecs1 = np.array([0,0,0,0,0,0])
# Select E0par and E0per that accounts for the manufacturing variability
# Suggestion is to run the min and max to obtain statisical variance in response
tE0per,fE0per,E0perVec = usnc.loadColumn(DATASET,'PerpExtrusion','Pre-Irrad.Eo(GPa)');
E0perVec*1E3 # Convert GPa to MPa
tE0par,fE0par,E0parVec = usnc.loadColumn(DATASET,'ParExtrusion','Pre-Irrad.Eo(GPa)');
E0parVec*1E3 # Convert GPa to MPa
# Comment and Uncomment as appropriate
#E0per = np.max(E0perVec)
#E0per = np.min(E0perVec)
E0per = np.mean(E0perVec)
#E0par = np.max(E0parVec)
#E0par = np.min(E0parVec)
E0par = np.mean(E0parVec)
In [27]:
# Symbolic variables T & F to define functions to be fitted with parameters indicated by P[#]
T,F = symbols('T,F')
form1 = 'F*(P[0] + P[1]*F + P[2]*F**2 + P[3]*T + P[4]*F*T**2 + P[5]*F**3 + P[6]*F**3*T)'
form2 = 'F*(P[0] + P[1]*T + P[2]*F + P[3]*T*F + P[4]*T**2 + P[5]*F**2 + P[6]*T**3+ P[7]*F**3 + P[8]*T**2*F + P[9]*T*F**2)'
form3 = '(P[0] + P[1]*T + P[2]*F + P[3]*T*F + P[4]*T**2 + P[5]*F**2 + P[6]*T**3+ P[7]*F**3 + P[8]*T**2*F + P[9]*T*F**2)'
form4 = '(P[0] + P[1]*T + P[2]*F + P[3]*T*F + P[4]*F**2 + P[5]*F**3 + P[6]*T**2*F + P[7]*T*F**2)'
formCTE0 = 'P[0] + P[1]*T + P[2]*T**2'
formE = 'P[0]'
# Load from FILENAME on an Excel Worksheet a specified Column of Data in addition to the Temperature and Fluence
# O1,O2,O3 = LOADCOLUMN(I1,I2,I3)
#
# O1 Temperature
# O2 Fluence
# O3 Column specified by I3
#
# I1 Filename of the Excel Workbook
# I2 Name of the Worksheet
# I3 Name of the Column to be Loaded
#
# ------------------------------------------------------------
#
# O1,O2,O3 = usnc.fitmodelfunc(I1,I2,I3,I4,I5,I6)
# Response (I3) is fitted as specified in I3 without any transformation
#
# O1. Generated Python Function (T,F)
# O2. Optimally Fitted Parameters with the number defined by I5 and I6
# O3. Generated Fortran Code with name specified by I4
#
# I1. Temperature,
# I2. Fluence,
# I3. Response to be fitted,
# I4. Name of the Fortran Function to be generated as O3
# I5. Form of the function to be fitted with I6 number of parameters
# I6. Number of parameters in the form specified by I5
# Available Fitting Functions (Response over Time and Fluence) are:
# 1. usnc.fitmodelfunc - fit model specified by form to the response (third argument)
# 2. usnc.fitlogmodelfunc - fit model specified by form after transforming Response to log10 domain
# All returned output is scaled back to the original domain from the log10 domain
#
# ------------------------------------------------------------
#
# Against Grain is indicated by per (perpendicular)
# With Grain is indicated by par (parallel)
E0per = E0per*1E3 # Convert GPa to MPa
CodeE0per = usnc.setconstantsub(E0per,'GetE0per')
tEE0per,fEE0per,EpE0per = usnc.loadColumn(DATASET,'PerpExtrusion','E/EoPre-Irrad.');
EpE0per = EpE0per
GetEoverE0per,XEoverE0per,CodeEoverE0per = usnc.fitlogmodel(tEE0per,fEE0per,EpE0per,'GetEoverE0per',form1,7)
E0par = E0par*1E3 # Convert GPa to MPa
CodeE0par = usnc.setconstantsub(E0par,'GetE0par')
tEE0par,fEE0par,EpE0par = usnc.loadColumn(DATASET,'ParExtrusion','E/EoPre-Irrad.');
EpE0par = EpE0par
GetEoverE0par,XEoverE0par,CodeEoverE0par = usnc.fitlogmodel(tEE0par,fEE0par,EpE0par,'GetEoverE0par',form1,7)
# Wiegner Strain / Linear Dimensional Change
tDLpar,fDLpar,DLpar = usnc.loadColumn(DATASET,'ParExtrusion','LinearDimensionalChangesDl/l0(%)')
YDLpar = DLpar/100. # Data is in percentage
GetDLpar,XDLpar,CodeDLpar = usnc.fitmodel(tDLpar,fDLpar,YDLpar,'Get_Wigner_par',form4,8)
tDLper,fDLper,DLper = usnc.loadColumn(DATASET,'PerpExtrusion','LinearDimensionalChangesDl/l0(%)')
YDLper = DLper/100. # Data is in percentage
GetDLper,XDLper,CodeDLper = usnc.fitmodel(tDLper,fDLper,YDLper,'Get_Wigner_per',form4,8)
# Coefficient of Thermal Expansion (CTE)
#tCTEpar,fCTEpar,CTEpar0 = usnc.loadColumn(DATASET,'ParExtrusion','Pre-Irrad.CTE0(10-6/K)')
#tCTEpar,fCTEpar,CTEpar = usnc.loadColumn(DATASET,'ParExtrusion','DCTE/CTE0(%)')
#YCTEpar = CTEpar0*CTEpar/100.*1E-6 # One data set is in percentage while the other in units 1E-6
#GetCTEpar,XCTEpar,CodeCTEpar = usnc.fitmodel(tCTEpar,fCTEpar,YCTEpar,'Get_CTE_par',form3,10)
tCTE0par,fCTE0par,CTEpar0 = usnc.loadColumn(DATASET,'ParExtrusion','Pre-Irrad.CTE0(10-6/K)')
YCTE0par = CTEpar0*1E-6
GetCTE0par,XCTE0par,CodeCTE0par = usnc.fit1Dlogmodel(tCTE0par,YCTE0par,'Get_CTE0par',formCTE0,3)
tCTEoCTE0par,fCTEoCTE0par,CTEoCTE0par = usnc.loadColumn(DATASET,'ParExtrusion','DCTE/CTE0(%)')
YCTEoCTE0par = CTEoCTE0par/100 # One data set is in percentage while the other in units 1E-6
GetCTEoCTE0par,XCTEpar,CodeCTEoCTE0par = usnc.fitmodel(tCTEoCTE0par,fCTEoCTE0par,YCTEoCTE0par,'Get_CTEoCTE0par',form4,8)
tCTE0per,fCTE0per,CTEper0 = usnc.loadColumn(DATASET,'PerpExtrusion','Pre-Irrad.CTE0(10-6/K)')
YCTE0per = CTEper0*1E-6
GetCTE0per,XDXCTE0per,CodeCTE0per = usnc.fit1Dlogmodel(tCTE0per,YCTE0per,'Get_CTE0per',formCTE0,3)
tCTEoCTE0per,fCTEoCTE0per,CTEoCTE0per = usnc.loadColumn(DATASET,'PerpExtrusion','DCTE/CTE0(%)')
YCTEoCTE0per = CTEoCTE0per/100 # One data set is in percentage while the other in units 1E-6
GetCTEoCTE0per,XCTEper,CodeCTEoCTE0per = usnc.fitmodel(tCTEoCTE0per,fCTEoCTE0per,YCTEoCTE0per,'Get_CTEoCTE0per',form4,8)
tCON,fCON,CON = usnc.loadColumn(DATASET,'Conductivity','ThermalConductivity(W/cmK)')
dummy1,dummy2,CONorient = usnc.loadColumn(DATASET,'Conductivity','Orientation(withregardtoextrudingdirection)')
tCONpar = tCON[np.array(CONorient=='parallel')]
fCONpar = fCON[np.array(CONorient=='parallel')]
CONpar = CON[np.array(CONorient=='parallel')]
GetCONpar,XCONpar,CodeCONpar = usnc.fitlogmodel(tCONpar,fCONpar,CONpar,'Get_Conductivity_par',form4,8)
tCONper = tCON[np.array(CONorient=='perpendicular')]
fCONper = fCON[np.array(CONorient=='perpendicular')]
CONper = CON[np.array(CONorient=='perpendicular')]
GetCONper,XCONper,CodeCONper = usnc.fitlogmodel(tCONper,fCONper,CONper,'Get_Conductivity_per',form4,8)
# Capture a list of minimum and maximum temperatures and fluences to generate extrapolation warning code
TminVec = [tEE0par.min(),tDLpar.min(),tDLper.min(),tCTE0per.min(),tCTE0par.min(),tCTEoCTE0per.min(),tCTEoCTE0par.min()]
TmaxVec = [tEE0par.max(),tDLpar.max(),tDLper.max(),tCTE0per.max(),tCTE0par.max(),tCTEoCTE0per.max(),tCTEoCTE0par.max()]
FminVec = [fEE0par.min(),fDLpar.min(),fDLper.min(),tCTEoCTE0per.min(),tCTEoCTE0par.min()]
FmaxVec = [fEE0par.max(),fDLpar.max(),fDLper.max(),tCTEoCTE0per.max(),tCTEoCTE0par.max()]
# Quality of the FITS Go To Bottom of Notebook to Section *Plot Control Scalar Functions*
# Uncomment to see Fortran Generated Code
#print(CodeE0per)
#print(CodeEoverE0per)
#print(CodeE0par)
#print(CodeEoverE0par)
#print(CODEDLPar)
#print(CODEDLPer)
print(CodeCTEoCTE0per)
print(CodeCTEoCTE0par)
#print(CodeCONper)
In [28]:
#Define Elastic Material Matrix
MatrixD = ("[[1/E{},-{}*1/E{},-{}*1/E{},0,0,0],".format(D1,v,D2,v,D3)+
"[-{}*1/E{},1/E{},-{}*1/E{},0,0,0],".format(v,D1,D2,v,D3)+
"[-{}*1/E{},-{}*1/E{},1/E{},0,0,0],".format(v,D1,v,D2,D3)+
"[0,0,0,1/({}*(EoverE0par+EoverE0per)/2),0,0],".format(G1)+
"[0,0,0,0,1/({}*(EoverE0par+EoverE0per)/2),0],".format(G2) +
"[0,0,0,0,0,1/({}*(EoverE0par+EoverE0per)/2)]]".format(G3))
#Compute the Python Elastic Material Matrix as Required by Primary and Secondary Creep Functions
def Get_InverseD(To,Fo,MatrixD):
EoverE0per = GetEoverE0per(To,Fo)
EoverE0par = GetEoverE0par(To,Fo)
Eper = EoverE0per*E0per
Epar = EoverE0par*E0par
InverseD = eval(MatrixD)
return InverseD
# Generate Fortran Code
InverseDCode = usnc.GetGet_invDelCode(D1,D2,D3,v,v,v,G1,G2,G3)
# Uncomment for test case and to see Fortran Generated Code
#print('InverseD Evaluated at T=500 and F=20 \n {}'.format(np.array(Get_InverseD(500,20,MatrixD))))
#print(InverseDCode)
In [29]:
def Get_Eel(T,F,stress):
dEeldS = Get_InverseD(T,F,MatrixD)
Eel = np.dot(dEeldS,stress)
return Eel,dEeldS
In [30]:
# Field Definition for Temperature and Fluence - Each expression needs to contain a variable i.e. 500.0 + 0.0X
# implues constant Temperature of 500 degC
TempPosTime = '400.0 + 8*Z'
FluencePosTime = '(0.05*time)*X'
#1 Generate
GetTempPosTime = lambda X,Y,Z,time: eval(TempPosTime)
X,Y,Z,time=symbols('X Y Z time');GetTempPosTimeCODE = usnc.GetGetTempPosTimeCode(fcode(eval(TempPosTime),assign_to="T"))
#print(GetTempPosTimeCODE)
GetFluencePosTime = lambda X,Y,Z,time: eval(FluencePosTime)
X,Y,Z,time=symbols('X Y Z time');GetFluencePosTimeCODE = usnc.GetGetFluencePosTimeCode(fcode(eval(FluencePosTime),assign_to="F"))
#print(GetFluencePosTimeCODE)
#Check functions
#Size of compoenent X,Y,Z assuming from 0 positive
numdis=5.0 #Number of discrete points to plot
size=[40,40,50] # Unit correspond to default mm
times=[1,5,10] # Time need to be equal FEM
counter=200 #since number of plots are unknowm start at random figure number
# Make data.
X = np.arange(0, size[0], size[0]/numdis)
Y = np.arange(0, size[1], size[1]/numdis)
Z = np.arange(0, size[2], size[2]/numdis)
X,Y,Z = np.meshgrid(X,Y,Z)
for time in times:
# Temperature plot
axT = usnc.axis3d(counter)
Tplot=eval(TempPosTime)
scatT = axT.scatter(X, Y, Z, c=Tplot, cmap=plt.jet())
axT.text2D(0, 1, "Temperature at time {}".format(time),fontsize = 20, transform=axT.transAxes)
axT.set_xlabel(r'$x [mm]$')
axT.set_ylabel(r'$y [mm]$')
axT.set_zlabel(r'$z [mm]$')
plt.colorbar(scatT)
plt.show()
# Fluence plot
axF = usnc.axis3d(counter+1)
Fplot=eval(FluencePosTime)
scatF = axF.scatter(X, Y, Z, c=Fplot, cmap=plt.jet())
axF.text2D(0, 1, "Fluence at time {}".format(time),fontsize = 20, transform=axF.transAxes)
axF.set_xlabel(r'$x [mm]$')
axF.set_ylabel(r'$y [mm]$')
axF.set_zlabel(r'$z [mm]m$')
plt.colorbar(scatF)
plt.show()
counter=counter+2
In [6]:
#Setup Wigner Strain Vector according to the define directions
VectorWigner = '[GetDL{}(To,Fo),GetDL{}(To,Fo),GetDL{}(To,Fo),0.0,0.0,0.0]'.format(D1,D2,D3)
def Get_Wigner_Strain(To,Fo):
return eval(VectorWigner)
WignerStrainCode = usnc.Get_EwCODE(D1,D2,D3)
# Uncomment to see Fortran Generated Code
#print(WignerStrainCode)
In [7]:
#Setup Thermal Strain Vector according to the define directions
VectorThermal = '[GetCTE0{}(To)*GetCTEoCTE0{}(To,Fo)*(To-Ti),GetCTE0{}(To)*GetCTEoCTE0{}(To,Fo)*(To-Ti),GetCTE0{}(To)*GetCTEoCTE0{}(To,Fo)*(To-Ti),0.0,0.0,0.0]'.format(D1,D1,D2,D2,D3,D3)
def Get_Thermal_Strain(To,Fo):
return eval(VectorThermal)
CTEStrainCode = usnc.Get_EthCODE(D1,D2,D3,Ti)
# Uncomment to see Fortran Generated Code
#print(CTEStrainCode)
In [8]:
Ecp,iDc_S,iDc,T,F = symbols('Ecp,iDc_S,iDc,T,F')
P = IndexedBase('P')
#Define the Primary Creep Rate Form - Relevant Derivatives for Consistent Tangent are Automatically Computed
PrimaryCreepRate_Form = '1/P[1]*(P[0]*iDc_S - Ecp)'
#Define the Secondary Creep Rate Form - Relevant Derivatives for Consistent Tangent are Automatically Computed
PrimaryCreepRate_Form_dEcp = str(eval(PrimaryCreepRate_Form).diff(Ecp))
PrimaryCreepRate_Form_dS = str(eval(PrimaryCreepRate_Form).diff(iDc_S)*iDc)
Ecp,iDc_S,iDc,T,F = symbols('Ecp,iDc_S,iDc,T,F')
P = IndexedBase('P')
SecondaryCreepRate_Form = '(P[2])*iDc_S'
SecondaryCreepRate_Form_dS = str(eval(SecondaryCreepRate_Form).diff(iDc_S)*iDc)
# Stress is converted to GPa to ease fitting.
# Any changes here need to be made to the Fortran in usnc.GetPrimaryRateCode
def Get_Ecp_rate(T,F,stress,Ecp,P):
iDc = Get_InverseD(T,0,MatrixD)
iDc = np.array(iDc)
iDc_S = np.dot(iDc,stress)
Ecp_rate = eval(PrimaryCreepRate_Form)
dEcp_rate_dEcp = eval(PrimaryCreepRate_Form_dEcp)
dEcp_rate_dS = eval(PrimaryCreepRate_Form_dS)
return np.array(Ecp_rate),np.array(dEcp_rate_dEcp),np.array(dEcp_rate_dS)
# Stress is converted to GPa to ease fitting.
# Any changes here need to be made to the Fortran in usnc.GetSecondaryRateCode
# Note iDc is computed for Fluence = 0, which differs from computing iDc(T,F) and then dividing by EoverE0@F=0
def Get_Ecs_rate(T,F,stress,P):
iDc = Get_InverseD(T,0,MatrixD)
iDc = np.array(iDc)
iDc_S = np.dot(iDc,stress)
Ecs_rate = eval(SecondaryCreepRate_Form)
dEcsrate_dS = eval(SecondaryCreepRate_Form_dS)
return np.array(Ecs_rate), np.array(dEcsrate_dS)
# Any changes made here need to be reflected in Get_Ecp in MainProgram.model
def GetEcp(T1,F1,stress1,Ecp1,T2,F2,stress2,P):
Ecp_rate1,dEcp_rate_dE1,dEcp_rate_dS1 = Get_Ecp_rate(T1,F1,stress1,Ecp1,P)
dF = F2-F1
Ecp2 = np.copy(Ecp1)
nrmRes = 1E9
Ecp_rate2,dEcp_rate_dE2,dEcp_rate_dS2 = Get_Ecp_rate(T2,F2,stress2,Ecp2,P)
dResdEcp = 1 - 0.5*dF*dEcp_rate_dE2
nrmRes0 = np.sum(np.array(Ecp2 - Ecp1 - 0.5*(Ecp_rate1 + Ecp_rate2))**2)**0.5
count = 1
while (nrmRes > 1E-10*nrmRes0) and (count < 100):
Ecp_rate2,dEcp_rate_dE2,dEcp_rate_dS2 = Get_Ecp_rate(T2,F2,stress2,Ecp2,P)
Res = np.array(Ecp2 - Ecp1 - 0.5*dF*(Ecp_rate1 + Ecp_rate2))
nrmRes = np.sum(np.array(Res)**2)**0.5
dResdEcp = 1 - 0.5*dF*dEcp_rate_dE2
Ecp2 = Ecp2 - Res/dResdEcp
count = count + 1
dEcpdS = 0.5*dF*dEcp_rate_dS2/dResdEcp
return Ecp2, dEcpdS
# Any changes made here need to be reflected in Get_Ecs in MainProgram.model
def GetEcs(T1,F1,stress1,Ecs1,T2,F2,stress2,P):
dF = F2-F1
Ecs_rate1,dEdS1 = Get_Ecs_rate(T1,F1,stress1,P)
Ecs_rate2,dEdS2 = Get_Ecs_rate(T2,F2,stress2,P)
Ecs2 = Ecs1 + 0.5*dF*(Ecs_rate1 + Ecs_rate2)
dEcsdS = 0.5*dF*dEdS2
return Ecs2, dEcsdS
# Any changes made here need to be reflected in umat in MainProgram.model
def umat(P,stress,Coords,time,dtime,statev,stran,dstran):
T2 = GetTempPosTime(Coords[0],Coords[1],Coords[2],time+dtime)
T1 = GetTempPosTime(Coords[0],Coords[1],Coords[2],time)
F2 = GetFluencePosTime(Coords[0],Coords[1],Coords[2],time+dtime)
F1 = GetFluencePosTime(Coords[0],Coords[1],Coords[2],time)
Eth = Get_Thermal_Strain(T2,F2)
Ew = Get_Wigner_Strain(T2,F2)
Ecp_t1 = statev[0:6]
Ecs_t1 = statev[6:]
stress1 = stress
nrmRes = 1.0
stress2 = stress1
while(nrmRes > 1E-8):
Eel,dEeldS = Get_Eel(T,F,stress)
Ecp2,dEcpdS = GetEcp(T1,F1,stress1,Ecp1,T2,F2,stress2,P)
Ecs,dEcspdS = GetEcs(T1,F1,stress1,Ecs2,T2,F2,stress2,P)
Res = np.array(stran + dstran - Eel - Ew - Eth - Ecs2 - Ecp2)
nrmRes = np.sum(Res**2)**0.5
dRdS = np.array(dEeldS) + np.array(dEcpdS) + np.array(dEcsdS)
idRdS = np.linalg.solve(dResdS,stress)
ddsdde = idRdS
stress = stress2
statev[0:6] = Ecp2
statev[6:] = Ecs2
return ddsdde,stress,statev
In [9]:
T,F,Y = usnc.loadColumn(DATASET,'WithGrain','TotalCreepStrain(%)');
Y = Y/100 # Adjust Percentage to Absolute Values
# Setup Residual to Fit the Total Creep Srain (%)
def R(PARAMETERS,T,F,Y):
from scipy.interpolate import interp1d
creepvector = np.zeros(Y.shape)
# Fit each Isotherm individually up to the maximum Fluence in the dataset
for Temp in np.unique(T):
Valid = np.array(T == Temp)
FVALID = F[Valid]
Fint,CP,CS = usnc.creepstrain(PARAMETERS,Temp,0,stress1,Ecp1,Ecs1,Temp,1.1*FVALID.max(),stress2,GetEcs,GetEcp,NumPointsCreepIntegration)
# Interpolate for the Fleuence
CPinterp = interp1d(Fint, CP)
CSinterp = interp1d(Fint, CS)
CPeval = CPinterp(FVALID)
CSeval = CSinterp(FVALID)
creepvector[Valid] = CPeval + CSeval
return creepvector - Y
# Caution - Infinite While Loop in GetEcp can Ensue Should Care not be Applied
# Optimization conducted three times to ensure convergence
for i in range(3):
res_lsq = least_squares(R, PCREEP,loss='soft_l1', f_scale=0.1, args=(T,F,Y),method='trf', ftol=1e-04, xtol=1e-04, gtol=1e-04,max_nfev=1000,verbose=2)
PCREEP = res_lsq['x']
print('Fitted Parameters {}'.format(PCREEP))
PrimaryRateCode = usnc.GetPrimaryRateCode(PCREEP,PrimaryCreepRate_Form,PrimaryCreepRate_Form_dEcp,PrimaryCreepRate_Form_dS)
SecondaryRateCode = usnc.GetSecondaryRateCode(PCREEP,SecondaryCreepRate_Form,SecondaryCreepRate_Form_dS)
TminVec.append(T.min());TmaxVec.append(T.max());FminVec.append(F.min());FmaxVec.append(F.max())
# Generate Extrapolation Warning Subroutine - Higest Low and Lowest High To Be Conservative on Overfitting
WarningCode = usnc.GetWarningCode(max(TminVec),min(TmaxVec),max(FminVec),min(FmaxVec))
# Note that at the bottom of this note the Section *Plot Control Primary and Secondary Creep* is to visualize
# the quality of the fits
In [10]:
# Write the Generated Fortran Code twice to ensure it is written to file.
for i in range(2):
header = open("MainCalculiXProgram.model","r")
w = open(FORTRANPATH+FORTRANFILE, "w")
for line in iter(header):
w.write(line)
for line in PrimaryRateCode:
w.write(line)
for line in SecondaryRateCode:
w.write(line)
for line in CodeE0per:
w.write(line)
for line in CodeE0par:
w.write(line)
for line in CodeEoverE0per:
w.write(line)
for line in CodeEoverE0par:
w.write(line)
for line in CodeDLpar:
w.write(line)
for line in CodeDLper:
w.write(line)
for line in CodeCTEoCTE0par:
w.write(line)
for line in CodeCTEoCTE0per:
w.write(line)
for line in CodeCTE0par:
w.write(line)
for line in CodeCTE0per:
w.write(line)
for line in InverseDCode:
w.write(line)
for line in GetFluencePosTimeCODE:
w.write(line)
for line in GetTempPosTimeCODE:
w.write(line)
for line in WignerStrainCode:
w.write(line)
for line in CTEStrainCode:
w.write(line)
for line in WarningCode:
w.write(line)
header.close()
# Automatically Updates CCX Source Code for Linux Systems Given Source Code Path with Write Access
from subprocess import call # check_output uncommend on linux system
RUNID = call("make",cwd=FORTRANPATH)
if RUNID == 0:
print('CCX Updated Successfully')
else:
print('CCX update failed')
In [11]:
# Write the Generated Fortran Code twice to ensure it is written to file.
for i in range(2):
header = open("MainANSYSProgram.model","r")
w = open(ANSYSPATH+ANSYSFILE, "w")
for line in iter(header):
w.write(line)
for line in PrimaryRateCode:
w.write(line)
for line in SecondaryRateCode:
w.write(line)
for line in CodeE0per:
w.write(line)
for line in CodeE0par:
w.write(line)
for line in CodeEoverE0per:
w.write(line)
for line in CodeEoverE0par:
w.write(line)
for line in CodeDLpar:
w.write(line)
for line in CodeDLper:
w.write(line)
for line in CodeCTEoCTE0par:
w.write(line)
for line in CodeCTEoCTE0per:
w.write(line)
for line in CodeCTE0par:
w.write(line)
for line in CodeCTE0per:
w.write(line)
for line in InverseDCode:
w.write(line)
for line in GetFluencePosTimeCODE:
w.write(line)
for line in GetTempPosTimeCODE:
w.write(line)
for line in WignerStrainCode:
w.write(line)
for line in CTEStrainCode:
w.write(line)
for line in WarningCode:
w.write(line)
header.close()
print("Finished Writing")
In [12]:
from os import system
TESTFILES = ['Test_CreepStrain','Test_ElasticStrain','Test_ThermalStrain','Test_WignerStrain','Test_TotalStrain']
#uncomment on linux systems
for TEST in TESTFILES:
if RUNID == 0:
os.chdir(DATAPATH)
system(CCXNAME+' '+TEST)
os.chdir(NOTEBOOKPATH)
In [13]:
dEeldS = Get_InverseD(500,20,MatrixD)
Eel = np.dot(dEeldS,stress2)
print(Eel)
In [14]:
Fint,CP,CS = usnc.creepstrain(PCREEP,500,0,stress1,Ecp1,Ecs1,500,20,stress2,GetEcs,GetEcp,10)
print(CP+CS)
In [15]:
Eth = Get_Thermal_Strain(500,20)
print(Eth)
In [16]:
Ewig = Get_Wigner_Strain(500,20)
print(Ewig)
In [17]:
Eel[0] + CP[-1] + CS[-1] + Eth[0] + Ewig[0]
Out[17]:
In [18]:
T_Max_Plot = 1500
In [19]:
Temps = np.linspace(T.min(),T_Max_Plot,11)
Fluences = np.linspace(F.min(),F.max(),11)
TT,FF = np.meshgrid(Temps,Fluences)
r,c = TT.shape
Ep = np.zeros((r,c))
Es = np.zeros((r,c))
for i in range(r):
Valid = np.array(TT == Temps[i])
FVALID = FF[Valid]
Fint,CP,CS = usnc.creepstrain(PCREEP,Temps[i],0,stress1,Ecp1,Ecs1,Temps[i],1.1*FVALID.max(),stress2,GetEcs,GetEcp,NumPointsCreepIntegration)
CPinterp = interp1d(Fint, CP)
CSinterp = interp1d(Fint, CS)
CPeval = CPinterp(FVALID)
CSeval = CSinterp(FVALID)
Ep[Valid] = CPeval
Es[Valid] = CSeval
ax10 = usnc.axis3d(100)
ax10.plot3D(T,F,Y,'k*');plt.xlabel('Temperature Cdeg');plt.ylabel('Fluence (dpa)');plt.title('Total Creep Strain %')
ax10.plot_surface(TT,FF,(Ep+Es),color='cyan')
ax10.plot_surface(TT,FF,Ep,color='red')
ax10.plot_surface(TT,FF,Es,color='green')
plt.show()
In [20]:
counter = 1000
for Temps in np.unique(T):
plt.figure(counter)
TFIX = Temps
Valid = np.array(T == TFIX)
FVALID = F[Valid]
Fint,CP,CS = usnc.creepstrain(PCREEP,TFIX,0,stress1,Ecp1,Ecs1,TFIX,1.1*FVALID.max(),stress2,GetEcs,GetEcp,NumPointsCreepIntegration)
CPinterp = interp1d(Fint, CP)
CSinterp = interp1d(Fint, CS)
CPeval = CPinterp(FVALID)
CSeval = CSinterp(FVALID)
plt.plot(Fint,CP+CS,'r-',label='Total');plt.xlabel('Fluence (dpa)');plt.ylabel('Total Creep Strain')
plt.plot(Fint,CP,'r-.',label='Primary')
plt.plot(Fint,CS,'r:',label='Secondary')
plt.plot(FVALID,Y[Valid],'r*',label='Data')
cod = r2_score(Y[Valid], CPeval+CSeval)
ve = explained_variance_score(Y[Valid], CPeval+CSeval)
mae = mean_absolute_error(Y[Valid], CPeval+CSeval)
medae = median_absolute_error(Y[Valid], CPeval+CSeval)
plt.title('Constant Temperature {} degC \n R2: {:05.3f} \n Variance Explained {:05.3f} \n Mean Absolute Error {:05.5f}\n Median Absolute Error {:05.5f} '.format(TFIX,
cod,ve,mae,medae))
plt.tight_layout()
plt.legend(loc='best')
counter += 1
In [21]:
GRID = np.zeros((11,11))
# E over E0 along PER and PAR
ax10 = usnc.axis3d(1)
ax10.plot3D(tEE0per,fEE0per,EpE0per,'k*');plt.xlabel('Temperature Cdeg');plt.ylabel('Fluence (dpa)');plt.title('E over E0 PER')
######
#TT,FF = np.meshgrid(np.linspace(tEE0per.min(),tEE0per.max(),11),np.linspace(0.0,fEE0per.max(),11))
TT,FF = np.meshgrid(np.linspace(tEE0per.min(),T_Max_Plot,11),np.linspace(0.0,fEE0per.max(),11))
#####
for i in range(TT.shape[0]):
for j in range(TT.shape[1]):
GRID[i,j] = GetEoverE0per(TT[i,j],FF[i,j])
ax10.plot_surface(TT,FF,GRID)
PredictY = []
t = np.array(tEE0per);f = np.array(fEE0per);myfunc = GetEoverE0per; YActual = np.array(EpE0per)
for i in range(len(t)):
PredictY.append(myfunc(t[i],f[i]))
cod = r2_score(np.array(YActual), PredictY)
ve = explained_variance_score(YActual, PredictY)
mae = mean_absolute_error(YActual, PredictY)
medae = median_absolute_error(YActual, PredictY)
plt.title('E over E0 PER \n R2: {:05.3f} \n Variance Explained {:05.3f} \n Mean Absolute Error {:05.5f}\n Median Absolute Error {:05.5f} '.format(
cod,ve,mae,medae))
plt.show()
ax10 = usnc.axis3d(2)
ax10.plot3D(tEE0par,fEE0par,EpE0par,'k*');plt.xlabel('Temperature Cdeg');plt.ylabel('Fluence (dpa)');plt.title('E over E0 PAR')
#####
TT,FF = np.meshgrid(np.linspace(tEE0par.min(),tEE0par.max(),11),np.linspace(0.0,fEE0par.max(),11))
TT,FF = np.meshgrid(np.linspace(tEE0par.min(),T_Max_Plot,11),np.linspace(0.0,fEE0par.max(),11))
####
for i in range(TT.shape[0]):
for j in range(TT.shape[1]):
GRID[i,j] = GetEoverE0par(TT[i,j],FF[i,j])
ax10.plot_surface(TT,FF,GRID)
PredictY = []
t = np.array(tEE0par);f = np.array(fEE0par);myfunc = GetEoverE0par; YActual = np.array(EpE0par)
for i in range(len(t)):
PredictY.append(myfunc(t[i],f[i]))
cod = r2_score(np.array(YActual), PredictY)
ve = explained_variance_score(YActual, PredictY)
mae = mean_absolute_error(YActual, PredictY)
medae = median_absolute_error(YActual, PredictY)
plt.title('E over E0 PAR \n R2: {:05.3f} \n Variance Explained {:05.3f} \n Mean Absolute Error {:05.5f}\n Median Absolute Error {:05.5f} '.format(
cod,ve,mae,medae))
plt.show()
In [22]:
# DL along PER
ax10 = usnc.axis3d(5)
ax10.plot3D(tDLper,fDLper,YDLper,'k*');plt.xlabel('Temperature Cdeg');plt.ylabel('Fluence (dpa)');plt.title('DL PER')
GRID = np.zeros((11,11))
########
#TT,FF = np.meshgrid(np.linspace(tDLper.min(),tDLper.max(),11),np.linspace(0,fDLper.max(),11))
TT,FF = np.meshgrid(np.linspace(tDLper.min(),T_Max_Plot,11),np.linspace(0,50,11))
######
for i in range(TT.shape[0]):
for j in range(TT.shape[1]):
GRID[i,j] = GetDLper(TT[i,j],FF[i,j])
ax10.plot_surface(TT,FF,GRID)
# Generate and Plot Relevant Statistics
PredictY = []
t = np.array(tDLper);f = np.array(fDLper);myfunc = GetDLper; YActual = np.array(YDLper)
for i in range(len(t)):
PredictY.append(myfunc(t[i],f[i]))
cod = r2_score(np.array(YActual), PredictY)
ve = explained_variance_score(YActual, PredictY)
mae = mean_absolute_error(YActual, PredictY)
medae = median_absolute_error(YActual, PredictY)
plt.title('Wigner ER \n R2: {:05.3f} \n Variance Explained {:05.3f} \n Mean Absolute Error {:05.5f}\n Median Absolute Error {:05.5f} '.format(
cod,ve,mae,medae))
plt.show()
# DL along PAR
ax10 = usnc.axis3d(6)
ax10.plot3D(tDLpar,fDLpar,YDLpar,'k*');plt.xlabel('Temperature Cdeg');plt.ylabel('Fluence (dpa)');plt.title('DL PAR')
GRID = np.zeros((11,11))
#######
#TT,FF = np.meshgrid(np.linspace(tDLpar.min(),tDLpar.max(),11),np.linspace(0,fDLpar.max(),11))
TT,FF = np.meshgrid(np.linspace(tDLpar.min(),T_Max_Plot,11),np.linspace(0,50,11))
#######
for i in range(TT.shape[0]):
for j in range(TT.shape[1]):
GRID[i,j] = GetDLpar(TT[i,j],FF[i,j])
ax10.plot_surface(TT,FF,GRID)
# Generate and Plot Relevant Statistics
PredictY = []
t = np.array(tDLpar);f = np.array(fDLpar);myfunc = GetDLpar; YActual = np.array(YDLpar)
for i in range(len(t)):
PredictY.append(myfunc(t[i],f[i]))
cod = r2_score(np.array(YActual), PredictY)
ve = explained_variance_score(YActual, PredictY)
mae = mean_absolute_error(YActual, PredictY)
medae = median_absolute_error(YActual, PredictY)
plt.title('Wigner Par \n R2: {:05.3f} \n Variance Explained {:05.3f} \n Mean Absolute Error {:05.5f}\n Median Absolute Error {:05.5f} '.format(
cod,ve,mae,medae))
plt.show()
In [23]:
# CTE along PAR
ax10 = usnc.axis3d(8)
ax10.plot3D(tCTEoCTE0per,fCTEoCTE0per,YCTEoCTE0per,'k*');plt.xlabel('Temperature Cdeg');plt.ylabel('Fluence (dpa)');plt.title('CTE PAR')
GRID = np.zeros((11,11))
TT,FF = np.meshgrid(np.linspace(tCTEoCTE0per.min(),T_Max_Plot,11),np.linspace(0,fCTEoCTE0per.max(),11))
for i in range(TT.shape[0]):
for j in range(TT.shape[1]):
GRID[i,j] = GetCTEoCTE0per(TT[i,j],FF[i,j])
ax10.plot_surface(TT,FF,GRID)
# Generate and Plot Relevant Statistics
PredictY = []
t = np.array(tCTEoCTE0per);f = np.array(fCTEoCTE0per);myfunc = GetCTEoCTE0par; YActual = np.array(YCTEoCTE0per)
for i in range(len(t)):
PredictY.append(myfunc(t[i],f[i]))
cod = r2_score(np.array(YActual), PredictY)
ve = explained_variance_score(YActual, PredictY)
mae = mean_absolute_error(YActual, PredictY)
medae = median_absolute_error(YActual, PredictY)
plt.title('CTE PER \n R2: {:05.3f} \n Variance Explained {:05.3f} \n Mean Absolute Error {:05.5f}\n Median Absolute Error {:05.5f} '.format(
cod,ve,mae,medae))
plt.show()
# CTE along PAR
ax10 = usnc.axis3d(9)
ax10.plot3D(tCTEoCTE0par,fCTEoCTE0par,YCTEoCTE0par,'k*');plt.xlabel('Temperature Cdeg');plt.ylabel('Fluence (dpa)');plt.title('CTE PER')
GRID = np.zeros((11,11))
TT,FF = np.meshgrid(np.linspace(tCTEoCTE0par.min(),T_Max_Plot,11),np.linspace(0,fCTEoCTE0par.max(),11))
for i in range(TT.shape[0]):
for j in range(TT.shape[1]):
GRID[i,j] = GetCTEoCTE0par(TT[i,j],FF[i,j])
ax10.plot_surface(TT,FF,GRID)
# Generate and Plot Relevant Statistics
PredictY = []
t = np.array(tCTEoCTE0par);f = np.array(fCTEoCTE0par);myfunc = GetCTEoCTE0par; YActual = np.array(YCTEoCTE0par)
for i in range(len(t)):
PredictY.append(myfunc(t[i],f[i]))
cod = r2_score(YActual, PredictY)
ve = explained_variance_score(YActual, PredictY)
mae = mean_absolute_error(YActual, PredictY)
medae = median_absolute_error(YActual, PredictY)
plt.title('CTE PAR \n R2: {:05.3f} \n Variance Explained {:05.3f} \n Mean Absolute Error {:05.5f}\n Median Absolute Error {:05.5f} '.format(
cod,ve,mae,medae))
plt.show()
In [24]:
# CONDUCTIVITY along PER
ax10 = usnc.axis3d(10)
ax10.plot3D(tCONper,fCONper,np.array(CONper),'k*');plt.xlabel('Temperature Cdeg');plt.ylabel('Fluence (dpa)');plt.title('Conductivity PER')
GRID = np.zeros((11,11))
TT,FF = np.meshgrid(np.linspace(tCONper.min(),T_Max_Plot,11),np.linspace(fCONper.min(),fCONper.max(),11))
for i in range(TT.shape[0]):
for j in range(TT.shape[1]):
GRID[i,j] = GetCONper(TT[i,j],FF[i,j])
ax10.plot_surface(TT,FF,GRID)
# Generate and Plot Relevant Statistics
PredictY = []
t = np.array(tCONper);f = np.array(fCONper);myfunc = GetCONper; YActual = np.array(CONper)
for i in range(len(t)):
PredictY.append(myfunc(t[i],f[i]))
cod = r2_score(np.array(YActual), PredictY)
ve = explained_variance_score(YActual, PredictY)
mae = mean_absolute_error(YActual, PredictY)
medae = median_absolute_error(YActual, PredictY)
plt.title('CONDUCTIVITY PER \n R2: {:05.3f} \n Variance Explained {:05.3f} \n Mean Absolute Error {:05.5f}\n Median Absolute Error {:05.5f} '.format(
cod,ve,mae,medae))
plt.show()
# CONDUCTIVITY along PAR
ax10 = usnc.axis3d(11)
ax10.plot3D(tCONpar,fCONpar,CONpar,'k*');plt.xlabel('Temperature Cdeg');plt.ylabel('Fluence (dpa)');plt.title('Conductivity PAR')
GRID = np.zeros((11,11))
TT,FF = np.meshgrid(np.linspace(tCONpar.min(),T_Max_Plot,11),np.linspace(fCONpar.min(),fCONpar.max(),11))
for i in range(TT.shape[0]):
for j in range(TT.shape[1]):
GRID[i,j] = GetCONpar(TT[i,j],FF[i,j])
ax10.plot_surface(TT,FF,GRID)
# Generate and Plot Relevant Statistics
PredictY = []
t = np.array(tCONpar);f = np.array(fCONpar);myfunc = GetCONpar; YActual = np.array(CONpar)
for i in range(len(t)):
PredictY.append(myfunc(t[i],f[i]))
cod = r2_score(np.array(YActual), PredictY)
ve = explained_variance_score(YActual, PredictY)
mae = mean_absolute_error(YActual, PredictY)
medae = median_absolute_error(YActual, PredictY)
plt.title('CONDUCTIVITY PAR \n R2: {:05.3f} \n Variance Explained {:05.3f} \n Mean Absolute Error {:05.5f}\n Median Absolute Error {:05.5f} '.format(
cod,ve,mae,medae))
plt.show()